import os
import win32api
import win32con
import win32gui
import threading

from shutil import copytree

from pystray import MenuItem
import pystray
from PIL import Image as pilimage

from SqrtS.tools.load_theme import load_theme
from SqrtS.Widgets.Text import Texts, LineTexts
from SqrtS.Layouts.FloatingLayout import FloatingLayout
from SqrtS.Core.core import FullScreenWindow
from SqrtS.tools.font import SqrtSFont
from SqrtS.Widgets.Image import Image
from SqrtS.Widgets.Button import ImageButton, ImageTextButton
from SqrtS.tools.image import ImageSurface
from SqrtS.Widgets.Input import Input
from SqrtS.Expand.WindowTransparency import window_transparency
from SqrtS.Core.TaskSystem import TERMINABLE_INFINITE
from SqrtS.Draw.lines import Line
from SqrtS.Widgets.Canvas import Canvas
from SqrtS.Core.event_process import MOUSE_WHEEL_UP, MOUSE_WHEEL_DOWN
from SqrtS.Expand.GlobalKeyBoard import GlobalKeyBoard

# from search import RoxySearch
from RoxySearch import RoxySearch
from MusicModule import MusicModule
from NovelModule import NovelModule
from TranslateModule import TranslateModule
from NetworkModule import NetworkModule
from BaikeModule import BaikeModule
from VSPparser import VSP
from Upd import ChkUpd


def get_hwnd(name):
    """
    获取窗口权柄
    :param name: 窗口名称
    :return: 窗口权柄int
    """
    ck = 0

    def get_all_hwnd(hwnd, mouse):
        """
        获取所有窗口的权柄
        :param hwnd:
        :param mouse:
        :return:
        """
        nonlocal ck
        hwnd_title = dict()
        if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):
            hwnd_title.update({hwnd: win32gui.GetWindowText(hwnd)})
        for h, t in hwnd_title.items():
            if t == name:
                ck = h

    win32gui.EnumWindows(get_all_hwnd, 0)

    return ck


class ScrollableImage(Image):

    def __init__(self, size, IDname, image_path, roxy):
        """
        定义一个可以通过鼠标滚轮翻页的图片显示控件
        :param size: 尺寸
        :param IDname: ID
        :param image_path: 图片路径
        :param roxy: Roxy主类
        """

        super().__init__(size, IDname, image_path)
        self.roxy = roxy

    def check_mouse_wheel_down(self, event, window):
        """
        当鼠标滚轮下滚时
        :param event: 事件函数
        :param window: 窗口
        :return:
        """

        self.roxy.next_res("")

    def check_mouse_wheel_up(self, event, window):
        """
        当鼠标滚轮上滚时
        :param event: 事件函数
        :param window: 窗口
        :return:
        """

        self.roxy.prev_res("")

    def register_for_event(self, window):
        """
        注册事件
        :param window: 窗口
        :return:
        """

        window.event_processor.register_event(MOUSE_WHEEL_DOWN, self.check_mouse_wheel_down)
        window.event_processor.register_event(MOUSE_WHEEL_UP, self.check_mouse_wheel_up)


class SystemStray:

    def __init__(self):
        """
        系统托盘类
        """

        self.roxy = None
        self.icon = None
        self.menu = None
        self.image = None

    def add(self):
        """
        添加图标项
        :return:
        """

        self.image = pilimage.open("Source/Roxy_Icon.ico")
        self.menu = (MenuItem("显示搜索框", self.roxy.show_wd), MenuItem("退出", self.roxy.close))
        self.icon = pystray.Icon("Roxy123123123", self.image, "Roxy", self.menu)
        self.icon.run()

    def start_stray(self, roxy):
        """
        启动系统托盘
        :param roxy: Roxy
        :return:
        """

        self.roxy = roxy
        thread = threading.Thread(target=self.add)
        thread.start()

    def notify(self, title, text):
        """
        显示系统提示消息
        :param title: 标题
        :param text: 内容文字
        :return:
        """

        if self.icon:
            self.icon.notify(title, text)


class Roxy:

    def __init__(self, system_vars):
        """
        Roxy主类
        :param system_vars:
        """

        self.edi = 3

        upd = ChkUpd()
        latest_edi = upd.chk_new_version()
        print("latest", latest_edi)
        if latest_edi == "x":
            ...
        else:
            latest = int(latest_edi)
            if latest > self.edi:
                print(latest, self.edi)
                win32api.MessageBox(0, "请前往 https://gitee.com/creeper2007/roxy-software-r/releases 下载最新版本", "有更新版本", win32con.MB_OK)

        self.CachePath = "C:/RoxyCache/"
        self.flayout1 = None
        self.wd = None
        if not os.path.exists("C:/RoxyCache/"):
            copytree('Source/CachePath', "C:/RoxyCache/")

        self.system_vars = system_vars

        self.search = RoxySearch()

        thr_scanfile = threading.Thread(target=self.search.scan)
        thr_scanfile.start()

        # **************************************************
        self.inp_size = [800, 80]  # 输入窗口大小
        self.input_size = [600, 50]  # 输入框大小
        self.inp_top = 120  # 输入框窗口距顶距离
        self.inp_ico_size = [40, 40]  # 输入窗口图标大小
        self.inp_ico_left = 20  # 输入窗口图标左距
        self.inp_ico_top = 20  # 输入窗口图标上距
        self.wid_res_size = [800, 500]  # 结果窗口大小
        self.row_height = 100  # 每条结果高度
        self.line_border = 1  # 分界线宽
        self.footer_size = [800, 40]  # 页脚窗口大小
        self.lrarrow_size = [30, 30]  # 页脚箭头大小
        self.icon_size = [50, 50]  # 文件图标大小
        self.icon_left = 20  # 文件图标左距
        self.icon_top = 25  # 文件图标上距
        self.filename_length = 20  # 文件名最大长度
        self.filename_left = 90  # 文件名左距
        self.filename_top = 15  # 文件名上距
        self.path_length = 60  # 路径最大长度
        self.path_name_left = 90  # 路径左距
        self.path_name_top = 65  # 路径上距
        # **************************************************

        self.screen_size = self.get_screen_size()
        self.lrpos = [(self.screen_size[0] - self.system_vars["inp_size"][0]) / 2, self.system_vars["inp_top"]]

        self.sword = ""
        self.last_word = ""

        self.res = []
        self.res_num = 0
        self.now_res = 0
        self.is_showing = False
        self.wid_res_shown = False
        self.wid_baike_shown = False
        self.wid_about_shown = False

        self.now_inp_ico = "search"

        self.in_music_pattern = False
        self.music_module_open = False
        self.in_dino_pattern = False
        self.in_translate_pattern = False
        self.in_novel_pattern = False
        self.in_baike_pattern = False
        self.novel_module_step = "none"

        self.now_tab = 0

        self.st = SystemStray()
        self.st.start_stray(self)

        self.kb = GlobalKeyBoard()
        self.kb.add('alt+space', self.hotkey_pressed)
        self.kb.run()

        self.network_module = NetworkModule()

        # os.popen("DLL\\RoxySearcher.exe")

        self.build_wd()


    def tab_expend(self, args):
        """
        标签选择
        :param args:
        :return:
        """

        self.tab_call(int(args.IDname[-1]))


    def hotkey_pressed(self):
        """
        热键检测
        :return:
        """

        if not self.is_showing:
            self.is_showing = True
            self.show_wd()
        else:
            self.is_showing = False
            self.hide_wd()


    def build_wd(self):
        """
        新建窗口
        :return:
        """

        # 创建主题
        theme1 = load_theme("Source\\theme_root\\theme\\")
        # 创建字体
        self.font_inp = SqrtSFont(50, "cnfont", theme1)
        self.font_filename = SqrtSFont(40, "cnfont", theme1)
        self.font_distname = SqrtSFont(15, "cnfont", theme1)
        self.font_tab = SqrtSFont(20, "cnfont", theme1)
        self.font_30 = SqrtSFont(30, "cnfont", theme1)

        # 控件定义
        wid_inp = Image(self.system_vars["inp_size"], IDname="wid_inp", image_path="Source/wid_inp.png")
        inp_search = Input(self.system_vars["input_size"], "inp_search", theme1, self.font_inp, text_color=(48, 48, 48),
                           cursor_color=(48, 48, 48))
        ico_inp = Image([40, 40], IDname="ico_inp", image_path="Source/Roxy_Icon.png")
        wid_footer = Image(self.system_vars["footer_size"], IDname="wid_footer", image_path="Source/wid_footer.png")

        # 首页布局绑定
        self.flayout1 = FloatingLayout(name="page1")
        self.flayout1.appends([wid_inp, inp_search, ico_inp, wid_footer])
        self.flayout1.bind_widgets_poses(
            {"wid_inp": self.lrpos, "inp_search": [self.lrpos[0] + 80, self.lrpos[1] + 15],
             "ico_inp": [self.lrpos[0] + self.system_vars["inp_ico_left"],
                         self.lrpos[1] + self.system_vars["inp_ico_top"]],
             "wid_footer": [self.lrpos[0], self.lrpos[1] + self.system_vars["inp_size"][1]]})

        # 新建窗口
        self.wd = FullScreenWindow()
        window_transparency(self.wd)
        self.wd.append_page(self.flayout1)

        tab_word = ["文件", "小说", "音乐", "百科", "翻译", "关于"]

        tab_image_list = [
            ImageSurface("Source\\tab.png"),
            ImageSurface("Source\\tab.png"),
            ImageSurface("Source\\tab.png")
        ]

        tab_image_list_after = [
            ImageSurface("Source\\tab.png"),
            ImageSurface("Source\\tab.png"),
            ImageSurface("Source\\tab.png")
        ]

        for i in range(6):
            wid_tab = ImageTextButton([100, 40], tab_image_list, IDname=f"wid_tab_{i}", button_text=tab_word[i],
                                      font=self.font_tab, style=[(0, 0, 255), True, None])

            self.flayout1.appends([wid_tab])
            self.flayout1.bind_widgets_poses({f"wid_tab_{i}": [self.lrpos[0] + 30 + i * 100, self.lrpos[1] - 39]})

            wid_tab.register_for_event(self.wd)

        for i in range(6):
            self.wd.get_widget_by_IDname(f"wid_tab_{i}").bind_call_func(self.tab_expend)

        self.wd.get_widget_by_IDname("wid_inp").reload_image("Source\\wid_inp_hover.png")
        self.wd.get_widget_by_IDname("wid_inp").resize_image(self.system_vars["inp_size"])

        # 注册页面
        def change_page_main():
            wid_inp.register_for_event(self.wd)
            inp_search.register_for_event(self.wd)

            inp_search.bind_finish_call(self.check_inp)

            inp_search.alive = True

        change_page_main()

        thr_auto_inp_chk = threading.Thread(target=self.auto_inp_chk)
        thr_auto_inp_chk.start()

        self.is_showing = True

        self.now_tab = 0
        self.tab_expend(self.wd.get_widget_by_IDname("wid_tab_0"))

        self.wd.run()


    @staticmethod
    def get_screen_size():
        """
        获取屏幕分辨率函数
        """
        return [win32api.GetSystemMetrics(0), win32api.GetSystemMetrics(1)]


    def auto_inp_chk(self):
        """
        自动检查输入框内容，用于更替图标、自动搜索等
        :return:
        """

        def check_inp():
            """
            检查函数
            :return:
            """

            self.sword = self.wd.get_widget_by_IDname("inp_search").return_input_text()

            if self.sword != self.last_word:
                if self.wid_res_shown or self.wid_baike_shown:
                    self.destroy_wid_res()

            if self.sword == "":
                if self.now_inp_ico != "search":
                    self.wd.get_widget_by_IDname("ico_inp").reload_image("Source\\Roxy_Icon.png")
                    self.wd.get_widget_by_IDname("ico_inp").resize_image([40, 40])
                    self.now_inp_ico = "search"

            elif self.sword[0] == "/":
                if self.now_inp_ico != "terminal":
                    self.wd.get_widget_by_IDname("ico_inp").reload_image("Source\\terminal.png")
                    self.wd.get_widget_by_IDname("ico_inp").resize_image([40, 40])
                    self.now_inp_ico = "terminal"

            self.last_word = self.sword

        self.wd.register_for_task(TERMINABLE_INFINITE, check_inp, 0.3, task_name="check_inp")


    def check_inp(self):
        """
        当按下回车键后执行的内容检查函数
        :return:
        """

        self.sword = self.wd.get_widget_by_IDname("inp_search").return_input_text()

        if self.sword == "/dino" or self.sword == "/Dino":
            os.popen(self.CachePath + "RoxyDino.exe")
            return

        if self.now_tab == 0:
            self.last_word = self.sword
            # self.search.roxysearch(self.sword, self.CachePath + "RoxySearch/search.roxycache",
            #                        self.CachePath + "RoxySearch/res.roxycache")
            # temp_res = self.search.return_res()

            temp_res = self.search.check(self.sword)

            self.res = []
            for r in temp_res:
                try:
                    if r.split("\\")[1] != "Windows":
                        self.res.append(r)
                except IndexError:
                    ...

            self.res_num = len(self.res)
            self.display_res()

        check_dict = {
            "1": self.search_novel, "2": self.search_music, "3": self.baike_search, "4": self.translate,
            "5": self.show_about_page, "0": lambda arg: self.tab_call(0)
        }

        check_dict[str(self.now_tab)](self.sword)


    def stop_chk_inp(self):
        """
        停止自动检查
        :return:
        """

        self.wd.destroy_terminable_task("check_inp")


    def call_extend(self, args):
        """
        点击列表项后调用的回调函数
        :param args:
        :return:
        """

        i = int(args.IDname[-1])
        self.call(i - 1)


    def display_res(self):
        """
        显示列表框
        :return:
        """

        self.res_num = len(self.res)

        if not self.wid_res_shown:
            wid_res = ScrollableImage(self.system_vars["wid_res_size"], IDname="wid_res",
                                      image_path="Source/wid_res.png", roxy=self)

            icos = [Image(self.system_vars["icon_size"], IDname=f"ico_{i}", image_path="Source/tm.png") for i in
                    range(1, 6)]

            names = [Texts("Name", (0, 0, 0), self.font_filename, IDname=f"name_{i}") for i in range(1, 6)]

            paths = [Texts("Path", (0, 0, 0), self.font_distname, IDname=f"path_{i}") for i in range(1, 6)]

            left_arrow_imglist = [
                ImageSurface("Source/arrow_left_circle_line.svg") for _ in range(3)
            ]

            right_arrow_imglist = [
                ImageSurface("Source/arrow_right_circle_line.svg") for _ in range(3)
            ]

            left_arrow = ImageButton(self.system_vars["lrarrow_size"], left_arrow_imglist, IDname="left_arrow")
            right_arrow = ImageButton(self.system_vars["lrarrow_size"], right_arrow_imglist, IDname="right_arrow")

            ca = Canvas()

            lines = [
                Line((0, 0, 0),
                     [self.lrpos[0] + 5,
                      self.lrpos[1] + self.system_vars["inp_size"][1] + self.system_vars["row_height"] * i],
                     [self.lrpos[0] + self.system_vars["inp_size"][0] - 5,
                      self.lrpos[1] + self.system_vars["inp_size"][1] + self.system_vars["row_height"] * i],
                     self.system_vars["line_border"])
                for i in range(1, 5)
            ]

            all_weights = [wid_res]
            all_weights += [i for i in icos + names + paths]
            self.flayout1.appends(all_weights + [left_arrow, right_arrow])

            self.flayout1.bind_widgets_poses({"wid_res": [self.lrpos[0], self.lrpos[1] + self.inp_size[1]],
                                              "ico_1": [self.lrpos[0] + self.icon_left,
                                                        self.lrpos[1] + self.inp_size[1] + self.icon_top],
                                              "name_1": [self.lrpos[0] + self.filename_left,
                                                         self.lrpos[1] + self.inp_size[1] + self.filename_top],
                                              "path_1": [self.lrpos[0] + self.path_name_left,
                                                         self.lrpos[1] + self.inp_size[1] + self.path_name_top],
                                              "ico_2": [self.lrpos[0] + self.icon_left,
                                                        self.lrpos[1] + self.inp_size[
                                                            1] + self.row_height * 1 + self.icon_top],
                                              "name_2": [self.lrpos[0] + self.filename_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 1 + self.filename_top],
                                              "path_2": [self.lrpos[0] + self.path_name_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 1 + self.path_name_top],
                                              "ico_3": [self.lrpos[0] + self.icon_left,
                                                        self.lrpos[1] + self.inp_size[
                                                            1] + self.row_height * 2 + self.icon_top],
                                              "name_3": [self.lrpos[0] + self.filename_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 2 + self.filename_top],
                                              "path_3": [self.lrpos[0] + self.path_name_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 2 + self.path_name_top],
                                              "ico_4": [self.lrpos[0] + self.icon_left,
                                                        self.lrpos[1] + self.inp_size[
                                                            1] + self.row_height * 3 + self.icon_top],
                                              "name_4": [self.lrpos[0] + self.filename_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 3 + self.filename_top],
                                              "path_4": [self.lrpos[0] + self.path_name_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 3 + self.path_name_top],
                                              "ico_5": [self.lrpos[0] + self.icon_left,
                                                        self.lrpos[1] + self.inp_size[
                                                            1] + self.row_height * 4 + self.icon_top],
                                              "name_5": [self.lrpos[0] + self.filename_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 4 + self.filename_top],
                                              "path_5": [self.lrpos[0] + self.path_name_left,
                                                         self.lrpos[1] + self.inp_size[
                                                             1] + self.row_height * 4 + self.path_name_top],
                                              "left_arrow": [self.lrpos[0] + self.inp_size[0] - 100,
                                                             self.lrpos[1] + self.inp_size[1] + self.wid_res_size[
                                                                 1] + 5],
                                              "right_arrow": [self.lrpos[0] + self.inp_size[0] - 60,
                                                              self.lrpos[1] + self.inp_size[1] + self.wid_res_size[
                                                                  1] + 5],
                                              "wid_footer": [self.lrpos[0],
                                                             self.lrpos[1] + self.inp_size[1] + self.wid_res_size[1]]
                                              })

            self.flayout1.append(ca)

            ca.appends_drawings(lines)

            self.wd.get_widget_by_IDname("wid_inp").reload_image("Source\\wid_inp_hover.png")
            self.wd.get_widget_by_IDname("wid_inp").resize_image(self.system_vars["inp_size"])

            wid_res.register_for_event(self.wd)

            for i in all_weights:
                i.register_for_event(self.wd)

            left_arrow.register_for_event(self.wd)
            right_arrow.register_for_event(self.wd)

            for i in names:
                i.bind_call_func(self.call_extend)

            left_arrow.bind_call_func(self.prev_res)
            right_arrow.bind_call_func(self.next_res)

            self.wid_res_shown = True

        if self.res_num == 0:
            self.res = ["没有结果"]

        for i in range(1, 5):
            if self.res_num <= i:
                self.res.append("")

        try:
            self.now_res = 0
            self.change_res_text()
            self.change_res_icon()
        except Exception as e:
            print(e)


    def call(self, num):
        """
        统一处理回调操作
        :param num: 项的下标
        :return:
        """

        if self.in_music_pattern:
            self.MuModule.build()
            self.MuModule.PlayMusic(num)
            return

        if self.in_novel_pattern:

            if self.novel_module_step == "choose_book":
                self.novel_choose_chapter(num)

            elif self.novel_module_step == "choose_chapter":
                self.novel_module_step = "none"

                novel_res = self.novel_module.get_content(self.novel_reslist[self.now_res + num]["url"])

                thr_run_bottle = threading.Thread(target=self.network_module.run_novel_network,
                                                  args=[self.novel_reslist[self.now_res + num]["name"], novel_res])
                thr_run_bottle.start()

                os.popen("DLL\\RoxyViewer.exe")

            return

        cmd = self.res[self.now_res + num + 1]

        if os.path.isdir(cmd):
            print(os.popen(f"explorer.exe {cmd}").read())

        else:
            print(os.popen(cmd).read())


    def tab_call(self, num):
        """
        统一处理标签的回调操作
        :param num: 标签页的下标
        :return:
        """

        if self.wid_about_shown and num != 5:
            self.destroy_wid_res()

        if num == 5:
            self.show_about_page("")

        tab_image_list = [
            ImageSurface("Source\\tab.png") for _ in range(3)
        ]

        tab_image_list_after = [
            ImageSurface("Source\\tab_after.png") for _ in range(3)
        ]

        self.wd.get_widget_by_IDname(f"wid_tab_{self.now_tab}").reset_imglist(tab_image_list)
        self.wd.get_widget_by_IDname(f"wid_tab_{num}").reset_imglist(tab_image_list_after)

        self.now_tab = num


    def change_res_text(self):
        """
        更改列表内容
        :return:
        """

        filename = self.res[self.now_res + 0].split("\\")[-1]
        path = self.res[self.now_res + 0]

        filename = self.cut_txt(filename)
        path = self.cut_txt(path)

        if len(filename) >= 28:
            filename = filename[0:10] + " ... " + filename[-13:]

        if len(path) >= 75:
            path = path[0:30] + " ... " + path[-40:]

        filename = self.restore_txt(filename)
        path = self.restore_txt(path)

        self.wd.get_widget_by_IDname("name_1").change_text(filename, (0, 0, 0), font=self.font_filename)
        self.wd.get_widget_by_IDname("path_1").change_text(path, (0, 0, 0), font=self.font_distname)

        filename = self.res[self.now_res + 1].split("\\")[-1]
        path = self.res[self.now_res + 1]

        filename = self.cut_txt(filename)
        path = self.cut_txt(path)

        if len(filename) >= 28:
            filename = filename[0:10] + " ... " + filename[-13:]

        if len(path) >= 75:
            path = path[0:30] + " ... " + path[-40:]

        filename = self.restore_txt(filename)
        path = self.restore_txt(path)

        self.wd.get_widget_by_IDname("name_2").change_text(filename, (0, 0, 0), font=self.font_filename)
        self.wd.get_widget_by_IDname("path_2").change_text(path, (0, 0, 0), font=self.font_distname)

        filename = self.res[self.now_res + 2].split("\\")[-1]
        path = self.res[self.now_res + 2]

        filename = self.cut_txt(filename)
        path = self.cut_txt(path)

        if len(filename) >= 28:
            filename = filename[0:10] + " ... " + filename[-13:]

        if len(path) >= 75:
            path = path[0:30] + " ... " + path[-40:]

        filename = self.restore_txt(filename)
        path = self.restore_txt(path)

        self.wd.get_widget_by_IDname("name_3").change_text(filename, (0, 0, 0), font=self.font_filename)
        self.wd.get_widget_by_IDname("path_3").change_text(path, (0, 0, 0), font=self.font_distname)

        filename = self.res[self.now_res + 3].split("\\")[-1]
        path = self.res[self.now_res + 3]

        filename = self.cut_txt(filename)
        path = self.cut_txt(path)

        if len(filename) >= 28:
            filename = filename[0:10] + " ... " + filename[-13:]

        if len(path) >= 75:
            path = path[0:30] + " ... " + path[-40:]

        filename = self.restore_txt(filename)
        path = self.restore_txt(path)

        self.wd.get_widget_by_IDname("name_4").change_text(filename, (0, 0, 0), font=self.font_filename)
        self.wd.get_widget_by_IDname("path_4").change_text(path, (0, 0, 0), font=self.font_distname)

        filename = self.res[self.now_res + 4].split("\\")[-1]
        path = self.res[self.now_res + 4]

        filename = self.cut_txt(filename)
        path = self.cut_txt(path)

        if len(filename) >= 28:
            filename = filename[0:10] + " ... " + filename[-13:]

        if len(path) >= 75:
            path = path[0:30] + " ... " + path[-40:]

        filename = self.restore_txt(filename)
        path = self.restore_txt(path)

        self.wd.get_widget_by_IDname("name_5").change_text(filename, (0, 0, 0), font=self.font_filename)
        self.wd.get_widget_by_IDname("path_5").change_text(path, (0, 0, 0), font=self.font_distname)


    def cut_txt(self, txt: str):
        """
        对过长的文字进行格式化省略
        :param txt: string，原始文字
        :return: string，格式化后的文字
        """

        txt_new = ""
        alphabet = "abcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&()-_=+;\'\""

        for i in txt:

            if i in alphabet:
                txt_new += i

            else:
                txt_new += i + '*'

        return txt_new


    def restore_txt(self, txt):
        """
        对过长的文字进行去格式化省略
        :param txt: 格式化后的文字
        :return: 去格式化后的文字
        """

        txt_ans = ""

        for i in txt:
            if i != '*':
                txt_ans += i

        return txt_ans


    def change_res_icon(self):
        """
        更改列表项的图标
        :return:
        """

        for i in range(5):
            self.wd.get_widget_by_IDname("ico_" + str(i + 1)).reload_image(
                self.find_right_icon(self.res[self.now_res + i]))


    def find_right_icon(self, filename):
        """
        根据文件名寻找合适正确的图标
        :param filename: 待查询的文件名
        :return: 图标文件路径
        """
        check_dict = {1: "Source\\book_6_line.svg", 2: "Source\\music_3_line.svg", 3: "Source\\translate_line.svg",
                      4: "Source\\translate_line.svg"}

        if self.now_tab in check_dict.keys():
            return check_dict[self.now_tab]

        suffix = filename.split(".")[-1]

        file_list_application = ["exe"]
        file_list_code = ["c", "cpp", "py", "h", "hpp", "go", "pyc"]
        file_list_word = ["doc", "docs", "docx", "wps"]
        file_list_ppt = ["ppt", "ppts", "pptx"]
        file_list_xls = ["xls", "xlsx", "xml", "csv"]
        file_list_pdf = ["pdf"]
        file_list_pic = ["jpg", "jpeg", "png", "bmp"]
        file_list_music = ["mp3", "wav"]
        file_list_video = ["mp4", "flv"]
        file_list_zip = ["zip", "7z", "rar", "rar5"]

        if suffix == "":
            return "Source\\tm.png"

        elif os.path.isdir(filename):
            return "Source\\folder_open_line.svg"

        elif suffix in file_list_application:
            return "Source\\classify_2_line.svg"

        elif suffix in file_list_code:
            return "Source\\code_line.svg"

        elif suffix in file_list_zip:
            return "Source\\file_zip_line.svg"

        elif suffix in file_list_music:
            return "Source\\file_music_line.svg"

        elif suffix in file_list_video:
            return "Source\\video_line.svg"

        elif suffix in file_list_pdf:
            return "Source\\pdf_line.svg"

        elif suffix in file_list_pic:
            return "Source\\pic_line.svg"

        elif suffix in file_list_word:
            return "Source\\doc_line.svg"

        elif suffix in file_list_ppt:
            return "Source\\ppt_line.svg"

        elif suffix in file_list_xls:
            return "Source\\xls_line.svg"

        else:
            return "Source\\file_unknown_line.svg"


    def next_res(self, args):
        """
        列表显示下一行
        :param args: 对象
        :return:
        """

        if self.res_num - self.now_res <= 5:
            ...

        else:
            self.now_res += 1
        self.change_res_text()
        self.change_res_icon()


    def prev_res(self, args):
        """
        列表显示上一行
        :param args: 对象
        :return:
        """

        if not self.now_res:
            ...

        else:
            self.now_res -= 1

        self.change_res_text()
        self.change_res_icon()


    def show_wd(self):
        """
        显示窗口
        :return:
        """

        self.wd.Layout.show()


    def hide_wd(self):
        """
        隐藏窗口
        :return:
        """

        self.wd.Layout.hide()


    def search_music(self, arg):
        """
        调用音乐模块搜索音乐
        :param arg: 对象
        :return:
        """

        self.in_music_pattern = True

        self.MuModule = MusicModule(self)
        self.music_results = self.MuModule.Search(arg)

        self.res = []

        for i in self.music_results:
            self.res.append(i["author"] + "\\" + i["title"])

        self.res_num = len(self.res)

        self.display_res()


    def search_novel(self, arg):
        """
        调用小说模块搜索小说
        :param arg: 对象
        :return:
        """

        self.in_novel_pattern = True
        self.novel_module_step = "choose_book"

        self.novel_module = NovelModule()
        self.novel_reslist = self.novel_module.search_novel(arg)

        self.res = []

        for i in self.novel_reslist:
            self.res.append(str("\\" + i["name"]))

        self.res_num = len(self.res)

        self.display_res()


    def novel_choose_chapter(self, num):
        """
        调用小说模块获取章节
        :param num: 项的下标
        :return:
        """

        self.novel_module_step = "choose_chapter"

        self.novel_module.now_book = self.now_res + num
        self.novel_reslist = self.novel_module.get_chapter(self.novel_reslist[self.now_res + num]["url"])

        self.res = []

        for i in self.novel_reslist:
            self.res.append(i['name'])

        self.display_res()


    def run_game_dino(self, args):
        """
        运行小恐龙游戏
        :param args: 对象
        :return:
        """

        self.in_dino_pattern = True

        with open(self.CachePath + "Network/network.roxycache", "w") as f:
            f.write("file:///C:/RoxyCache/dino/index.html")

        os.popen("DLL\\RoxyEbookReader.exe")


    def run_cmd(self, args):
        """
        执行cmd命令
        :param args: 对象
        :return:
        """

        try:
            os.popen(args["command"])

        except Exception as e:
            print(e)

        self.wd.get_widget_by_IDname("inp_search").clear_text()


    def translate(self, arg):
        """
        中英互译（自动识别）
        :param arg: 对象
        :return:
        """

        self.in_translate_pattern = True

        data = {"source": arg,
                "from": 1,
                "to": 4,
                }

        translate_module = TranslateModule()

        self.res = []

        self.res.append(translate_module.post_request(data))

        self.res_num = len(self.res)
        self.display_res()


    def fanyi(self, args):
        """
        支持多语种的翻译
        :param args: 对象
        :return:
        """

        self.in_translate_pattern = True

        data = {"source": args["word"],
                "from": 1,
                "to": self.get_language_code(args["to"]),
                }

        translate_module = TranslateModule()

        self.res = []

        self.res.append(translate_module.post_request(data))

        self.res_num = len(self.res)
        self.display_res()


    def eng_to_chn(self, args):
        """
        英语翻译为中文
        :param args: 对象
        :return:
        """

        self.translate({"to": 2, "word": args["word"]})


    def chn_to_eng(self, args):
        """
        中文翻译成英文
        :param args: 对象
        :return:
        """

        self.translate({"to": 4, "word": args["word"]})


    def baike_search(self, key):
        """
        调用百度百科模块搜索百科
        :param key: 搜索关键词
        :return:
        """

        self.in_baike_pattern = True

        baike_module = BaikeModule()
        url = "https://baike.baidu.com/search/word?fromModule=lemma_search-box&lemmaId=lemma_search-box&word=" + key
        res = baike_module.get_request(url)

        self.show_baike(res)


    def show_baike(self, dict):
        """
        显示百科模块的结果
        :param dict: 字典，存储结果
        :return:
        """

        if self.wid_baike_shown:
            return

        self.wid_baike_shown = True

        wid_baike = Image(self.wid_res_size, IDname="wid_baike", image_path="Source/wid_res.png")

        main_title = Texts(dict["main_title"], (0, 0, 0), self.font_inp, IDname="baike_main_title")
        sub_title = Texts(dict["sub_title"], (0, 0, 0), self.font_filename, IDname="baike_sub_title")
        contains = LineTexts(dict["text"], (0, 0, 0), self.font_tab, line_length=36, IDname="baike_contains")

        self.wd.Layout.appends([wid_baike, main_title, sub_title, contains])

        self.wd.Layout.bind_widgets_poses({
            "baike_main_title": [self.lrpos[0] + 30, self.lrpos[1] + self.inp_size[1] + 20],
            "baike_sub_title": [self.lrpos[0] + 30, self.lrpos[1] + self.inp_size[1] + 80],
            "baike_contains": [self.lrpos[0] + 30, self.lrpos[1] + self.inp_size[1] + 140]})

        self.flayout1.bind_widgets_poses({"wid_baike": [self.lrpos[0], self.lrpos[1] + self.inp_size[1]],
                                          "wid_footer": [self.lrpos[0],
                                                         self.lrpos[1] + self.inp_size[1] + self.wid_res_size[1]]})

        wid_baike.register_for_event(self.wd)
        main_title.register_for_event(self.wd)
        sub_title.register_for_event(self.wd)
        contains.register_for_event(self.wd)


    def get_language_code(self, language):
        """
        获取语言对应的代码
        :param language: 语言名
        :return:
        """

        if 0 <= int(language) <= 9:
            return language
        if language == "zh" or language == "中文":
            return 2
        if language == "en" or language == "英文":
            return 4
        return 1


    def destroy_wid_res(self):
        """
        销毁结果显示
        :return:
        """

        self.flayout1.bind_widgets_poses({"wid_footer": [self.lrpos[0], self.lrpos[1] + self.inp_size[1]]})

        if self.wid_res_shown:

            target_list = ["canvas", "wid_res", "left_arrow", "right_arrow"]

            for i in target_list:
                self.wd.get_widget_by_IDname(i).destroy_widget(self.wd)

            self.wid_baike_shown = False

            for i in range(1, 6):
                self.wd.get_widget_by_IDname(f"name_{i}").destroy_widget(self.wd)
                self.wd.get_widget_by_IDname(f"path_{i}").destroy_widget(self.wd)
                self.wd.get_widget_by_IDname(f"ico_{i}").destroy_widget(self.wd)

            self.wid_res_shown = False

        if self.wid_baike_shown:

            target_list = ["wid_baike", "baike_main_title", "baike_sub_title", "baike_contains"]

            for i in target_list:
                self.wd.get_widget_by_IDname(i).destroy_widget(self.wd)

            self.wid_baike_shown = False

        if self.wid_about_shown:

            target_list = ["wid_about", "about_main_title", "about_sub_title", "about_text3"]

            for i in target_list:
                self.wd.get_widget_by_IDname(i).destroy_widget(self.wd)

            self.wid_about_shown = False


    def close(self):
        """
        关闭窗口
        :return:
        """

        self.wd.close()


    def show_about_page(self, sword):
        """
        显示关于页面
        :param sword: 关键词
        :return:
        """

        if self.wid_about_shown:
            return

        self.wid_about_shown = True

        wid_about = Image(self.wid_res_size, IDname="wid_about", image_path="Source/wid_res.png")

        main_title = Texts("关于 Roxy 3.0", (0, 0, 0), self.font_inp, IDname="about_main_title")
        sub_title = Texts("最新版本：https://gitee.com/creeper2007/roxy-software-r/releases", (0, 0, 0), self.font_30,
                          IDname="about_sub_title")
        text3 = Texts("已基于AGPL-3.0协议在Gitee开源", (0, 0, 0), self.font_tab, IDname="about_text3")

        self.wd.Layout.appends([wid_about, main_title, sub_title, text3])

        self.wd.Layout.bind_widgets_poses({
            "about_main_title": [self.lrpos[0] + 30, self.lrpos[1] + self.inp_size[1] + 20],
            "about_sub_title": [self.lrpos[0] + 30, self.lrpos[1] + self.inp_size[1] + 90],
            "about_text3": [self.lrpos[0] + 30, self.lrpos[1] + self.inp_size[1] + 160]})

        self.flayout1.bind_widgets_poses({"wid_about": [self.lrpos[0], self.lrpos[1] + self.inp_size[1]],
                                          "wid_footer": [self.lrpos[0],
                                                         self.lrpos[1] + self.inp_size[1] + self.wid_res_size[1]]})

        wid_about.register_for_event(self.wd)
        main_title.register_for_event(self.wd)
        sub_title.register_for_event(self.wd)
        text3.register_for_event(self.wd)


if __name__ == '__main__':
    r = Roxy(VSP(path="./weights_values.vsp").get_system_vars())
